#ifndef DRAWABLE_H
#define DRAWABLE_H

#include "bga/system/Resource.h"

#include "bga/graphics/VertexBufferObject.h"

#include "bga/math/Vector3.h"

/**
 * \namespace bga
 * \brief API namespace
 */
namespace bga
{

/*!
 * \class Drawable
 * \brief This class represents a drawable object
 */
class BOARD_HELL_ENGINE Drawable : public Resource
{
	public:
		Drawable();
		virtual ~Drawable();

        /*!
         * \fn const float* getVertexArray() const
         * \brief Get the vertex array
         */
		const float* getVertexArray() const;

        /*!
         * \fn const float* getTexCoordArray() const
         * \brief Get the array of texture coordinates
         */
		const float* getTexCoordArray() const;

        /*!
         * \fn const float* getColorsArray() const
         * \brief Get the color array
         */
		const float* getColorsArray() const;

        /*!
         * \fn const float* getNormalArray() const
         * \brief Get the normals array
         */
		const float* getNormalsArray() const;

        /*!
         * \fn const float* getVertexAttribArray() const
         * \brief Get the vertex attributes array
         */
        const float* getVertexAttribArray() const;

        /*!
         * \fn const unsigned short* getIndexArray() const
         * \brief Get the index array
         */
		const unsigned short* getIndexArray() const;

		/*!
         * \fn void setVertexArray(const float* vertexArray, unsigned int vertexArraySize)
         * \brief Set the vertex array
         */
		void setVertexArray(const float* vertexArray, unsigned int vertexArraySize);

        /*!
         * \fn void setTexCoordArray(const float* texCoordArray, unsigned int texCoordArraySize)
         * \brief Set the array of texture coordinates
         */
		void setTexCoordArray(const float* texCoordArray, unsigned int texCoordArraySize);

        /*!
         * \fn void setColorsArray(const float* colorsArray, unsigned int colorsArraySize)
         * \brief Set the color array
         */
		void setColorsArray(const float* colorsArray, unsigned int colorsArraySize);

        /*!
         * \fn void setNormalArray(const float* normalArray, unsigned int normalArraySize)
         * \brief Set the normals array
         */
        void setNormalsArray(const float* normalsArray, unsigned int normalsArraySize);


        /*!
         * \fn void setVertexAttribArray(const float* vertexAttribArray, unsigned int vertexAttribArraySize)
         * \brief Set the vertex attributes array
         */
        void setVertexAttribArray(const float* vertexAttribArray, unsigned int vertexAttribArraySize);

		/*!
         * \fn void setIndexArray(unsigned short* indexArray, unsigned int indexArraySize)
         * \brief Set the index array
         */
		void setIndexArray(unsigned short* indexArray, unsigned int indexArraySize);

		/*!
         * \fn GLsizei getVertexArraySizeInByte() const
         * \brief Get the array size in byte
         */
		GLsizei getVertexArraySizeInByte() const;

		/*!
         * \fn GLsizei getTexCoordArraySizeInByte() const
         * \brief Get the array size in byte
         */
		GLsizei getTexCoordArraySizeInByte() const;

		/*!
         * \fn GLsizei getColorsArraySizeInByte() const
         * \brief Get the array size in byte
         */
		GLsizei getColorsArraySizeInByte() const;

        /*!
         * \fn GLsizei getNormalArraySizeInByte() const
         * \brief Get the array size in byte
         */
		GLsizei getNormalsArraySizeInByte() const;

        /*!
         * \fn GLsizei getVertexAttribArraySizeInByte() const
         * \brief Get the array size in byte
         */
		GLsizei getVertexAttribArraySizeInByte() const;

		/*!
         * \fn GLsizei getIndexArraySizeInByte() const
         * \brief Get the array size in byte
         */
		GLsizei getIndexArraySizeInByte() const;

        /*!
         * \fn unsigned int getVertexArraySize() const
         * \brief Get the number of element in the array
         */
		unsigned int getVertexArraySize() const;

		/*!
         * \fn unsigned int getTexCoordArraySize() const
         * \brief Get the number of element in the array
         */
		unsigned int getTexCoordArraySize() const;

		/*!
         * \fn unsigned int getColorsArraySize() const
         * \brief Get the number of element in the array
         */
		unsigned int getColorsArraySize() const;

        /*!
         * \fn unsigned int getNormalArraySize() const
         * \brief Get the number of element in the array
         */
		unsigned int getNormalsArraySize() const;

        /*!
         * \fn unsigned int getVertexAttribArraySize() const
         * \brief Get the number of element in the array
         */
		unsigned int getVertexAttribArraySize() const;

		/*!
         * \fn unsigned int  getIndexArraySize() const
         * \brief Get the number of element in the array
         */
		unsigned int getIndexArraySize() const;

        void setNbTexCoordPerElement(unsigned int nbTexCoordPerElement);

        unsigned int getNbTexCoordPerElement() const;

        /*!
         * \fn int getPrimitive() const
         * \brief Get the used opengl primitive
         */
		GLenum getPrimitive() const;

		/*!
         * \fn void setPrimitive(GLenum primitive)
         * \brief Set the used opengl primitive
         */
		void setPrimitive(GLenum primitive);

        /*!
         * \fn int getVBO() const
         * \brief Get the VBO which store drawable data
         */
		VertexBufferObject* getVBO() const;

        /*!
         * \fn VertexBufferObject getEBO() const
         * \brief Get the VBO which store drawable indices
         */
		VertexBufferObject* getEBO() const;

        /*!
         * \fn void createAndConfigureVBOs()
         * \brief create and configure vbos according to drawable data
         */
        void createAndConfigureVBOs();

        /*!
         * \brief get the size of the model based on AABB bounding box way
         * \return the size of the drawable
         */
        Vector3f getSize();


	private:
        float* vertexArray;           ///!< Vertex Coordinates Array
        float* colorsArray;           ///!< Vertex Colors Array
        float* texCoordArray;         ///!< Vertex Texture Coordinates Array
        float* normalsArray;          ///!< Vertex Normals Array
        float* smoothedNormalsArray;  ///!< Vertex Smoothed Normal Array
        float* vertexAttribArray;       ///!< Vertex Attributes Array
        unsigned short* indexArray;   ///!< Index Vertex Array


        unsigned int vertexArraySize;     ///!< Vertex Coordinates Array Size
        unsigned int colorsArraySize;     ///!< Vertex Colors Array Size
        unsigned int texCoordArraySize;   ///!< Vertex Texture Coordinates Array Size
        unsigned int normalsArraySize;    ///!< Vertex Normals Array Size
        unsigned int vertexAttribArraySize; ///!< Vertex Attributes Array Size
        unsigned int indexArraySize;      ///!< Index Vertex Array Size

        GLsizei vertexArraySizeInByte;    ///!< Vertex Coordinates Array Size In Bytes
        GLsizei colorsArraySizeInByte;    ///!< Vertex Coordinates Array Size In Bytes
        GLsizei texCoordArraySizeInByte;  ///!< Vertex Coordinates Array Size In Bytes
        GLsizei normalsArraySizeInByte;   ///!< Vertex Coordinates Array Size In Bytes
        GLsizei vertexAttribArraySizeInByte;    ///!< Vertex Attributes Array Size In Bytes
        GLsizei indexArraySizeInByte;     ///!< Vertex Coordinates Array Size In Bytes

        unsigned int nbTexCoordPerElement;


    protected:
        GLenum primitive;

        /// VBO used to draw the Drawable
        VertexBufferObject* vbo;
        VertexBufferObject* ebo;

};

}

#endif // DRAWABLE_H

